package com.xfzp.android.ms;

import java.util.Arrays;
import java.util.List;

import com.xfzp.d3.Axis;
import com.xfzp.d3.Coord;
import com.xfzp.d3.Cube;
import com.xfzp.d3.Geometry;
import com.xfzp.d3.Ray;
import com.xfzp.d3.Shape;
import com.xfzp.d3.World;

/**
 * 
 * @author AndroidApe
 * @version 2012-11-2
 */
public class Layers {
	private Layer[] layers;

	public Layers() {
		layers = initLayers();
	}

	public Layer getLayer(int i) {
		return layers[i];
	}

	public AbleLayer rayPickup(World k, Ray ray, Coord dir) {
		Shape s = getBorderCube(k);
		Ray.Picker p = ray.pick(s);
		if (p == null)
			return null;
		int face = p.index;
		face = face / 2;
		float abs_x = Math.abs(dir.x());
		float abs_y = Math.abs(dir.y());
		float abs_z = Math.abs(dir.z());
		int sl;
		if (face == 0 || face == 3) {
			sl = abs_x > abs_y ? 3 : 0;
		} else if (face == 1 || face == 4) {
			sl = abs_z > abs_x ? 0 : 6;
		} else if (face == 2 || face == 5) {
			sl = abs_y > abs_z ? 6 : 3;
		} else {
			return null;
		}

		Coord pc = ray.count(p.range);
		double w0;
		if (sl == 0) {
			w0 = Geometry.point2Plane(pc, s.v(0), s.v(1), s.v(4));
		} else if (sl == 3) {
			w0 = Geometry.point2Plane(pc, s.v(0), s.v(3), s.v(4));
		} else if (sl == 6) {
			w0 = Geometry.point2Plane(pc, s.v(0), s.v(1), s.v(2));
		} else
			return null;

		double w = Math.sqrt(s.v(0).dot(s.v(1))) / 3;
		sl += w0 > 2 * w ? 2 : (w0 > w ? 1 : 0);
		return new AbleLayer(sl, face < 3);
	}

	public Cube getBorderCube(World w) {
		int[] li = new int[] { 6, 8 };
		int[] ii = new int[] { 0, 2, 4, 6 };
		List<Integer> vi = Arrays.asList(new Integer[] { 0, 6, 8, 2, 17, 23,
				25, 19 });
		Cube c = new Cube();
		for (int l : li) {
			int[] cii = getLayer(l).getCubeIndex();
			for (int i : ii) {
				Shape s = w.get(cii[i]);
				int t = vi.indexOf(cii[i]);
				c.set(t, s.v(t));
			}
		}
		return c;
	}

	private Layer[] initLayers() {
		return new Layer[] {
				new Layer(Axis.X, new int[] { 0, 9, 17, 20, 23, 14, 6, 3, 12 }),
				new Layer(Axis.X, new int[] { 1, 10, 18, 21, 24, 15, 7, 4 }),
				new Layer(Axis.X, new int[] { 2, 11, 19, 22, 25, 16, 8, 5, 13 }),
				new Layer(Axis.Y, new int[] { 0, 1, 2, 11, 19, 18, 17, 9, 10 }),
				new Layer(Axis.Y, new int[] { 3, 4, 5, 13, 22, 21, 20, 12 }),
				new Layer(Axis.Y, new int[] { 6, 7, 8, 16, 25, 24, 23, 14, 15 }),
				new Layer(Axis.Z, new int[] { 0, 3, 6, 7, 8, 5, 2, 1, 4 }),
				new Layer(Axis.Z, new int[] { 9, 12, 14, 15, 16, 13, 11, 10 }),
				new Layer(Axis.Z, new int[] { 17, 20, 23, 24, 25, 22, 19, 18,
						21 }) };
	}
}
